//类型别名
type Ck = string|number;
let str:Ck = 'Mrck';


//交叉类型
//# 交叉类型：交叉类型是将多个类型合并为一个类型。 
type a = {name:string}
type b = {age:number}

let obj:a&b = {
  name:'案例',
  age:20
};

//同样也可以用于接口
interface Ia {
  name:string
}
interface Ib {
  age:number
}
let obj1:Ia&Ib = {
  name:'艾伦',
  age:29
}

// # Unknown
// - 顶级类型，它可以接收任何类型，但是无法赋值给其他类型（除 any 和 unknown 本身之外）
//因此在需要接收所有类型的场景下，优先考虑用 unknown 代替 any。

let c:unknown = '我是谁';
let d = '我在哪里';
// d = c;//错误写法

// c=d;//可以赋值



//typeof获取类型,注意不仅可获取基本类型，引用类型也可以获取
let obj3 = {
  name:'三笠',
  age:18
};
//这里使用typeof获取类型，保存到别名中
type Ob =  typeof obj3
//使下一个别名也要符合类型
let obj4:Ob = {
  name:'艾伦',
  age:20
}

//keyof操作符
// - keyof 操作符用来获取一个类型所有的键值，与 Object.keys 类似，前者获取 interface 的键，后者获取对象的键。

//这里获取所有的键
interface IP {
  name:string
  age:number
}
//obj5的值只能是Ip的键
let obj5:keyof IP  = 'age';//我们只能使用 name 或 age

//使用keyof对函数的key值限制
interface Ifn {
  name:string
  age:number
}
// - 通常 keyof 会配合着 typeof 使用：
function myFn (obj:Ifn,str:keyof typeof obj):keyof Ifn {
  return 'age'
}

myFn({name:'三笠',age:19},'name');


// # in
// - in 操作符通常用来实现枚举类型遍历
//假如你有所有对象的键名
type Keys = 'name' | 'age';
type Person = {
  [K in Keys]: any;
}
let obj8:Person = {
  name:'三笠',
  age:123
}
